# -*- coding: UTF-8 -*-
import pandas as pd
import numpy as np
import tensorflow as tf
import os
import gp_db

# 进行One-hot编码
def dense_to_one_hot(labels_dense , num_classes):
    num_labels = labels_dense.shape[0]
    index_offset = np.arange(num_labels) * num_classes
    labels_one_hot = np.zeros((num_labels, num_classes))
    labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
    return labels_one_hot

def tf_cnn_train(data,label_data ,model_name , times):
    # 3 对分类结果进行处理
    labels_count = np.unique(label_data).shape[0]
    data_len = data.shape[1]
    print('结果的种类=> {0}'.format(labels_count))
    labels = dense_to_one_hot(label_data, labels_count)
    labels = labels.astype(np.uint8)
    print('结果的数量： ( {0[0]},{0[1]})'.format(labels.shape))

    # 4 把辖入数据划分训练集和验证集
    train_size = data.shape[0]
    #  取训练集中的1/20的数据作为回测数据
    VALIDATION_SIZE = int(train_size/20)
    # VALIDATION_SIZE = int(len(images)/10)
    validation_images = data[:VALIDATION_SIZE]
    validation_labels = labels[:VALIDATION_SIZE]
    train_data = data[VALIDATION_SIZE:]
    train_labels = labels[VALIDATION_SIZE:]

    # 5 对训练集进行分批
    batch_size = 100
    n_batch = len(train_data) / batch_size

    # 6 创建一个简单的神经网络用来对图片进行识别
    # 权重矩阵 设为都 0 的矩阵
    weights = tf.Variable(tf.zeros([data_len, labels_count]))
    # 偏移量
    biases = tf.Variable(tf.zeros([labels_count]))
    x = tf.placeholder('float', shape=[None, data_len],name="input_image")
    y = tf.placeholder('float', shape=[None, labels_count])
    #
    result = tf.matmul(x, weights) + biases
    prediction = tf.nn.softmax(result)

    # 7 创建损失函数，以交又熵的平均值为衡量
    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits (labels = y , logits=prediction))
    # 8 用梯度下降法优化參数
    train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

    # 9 初始化变置
    init = tf.global_variables_initializer()
    # 10 计算准确度
    correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1,name='czcprediction'))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

    #保存模型
    saver = tf.train.Saver(max_to_keep=4)
    strs = ""
    with tf.Session() as sess:
        # 初始化
        sess.run(init)
        #循环50轮
        for epoch in range(times):
            for batch in range(int(n_batch)):
                #按照分片取出数据
                batch_x = train_data[batch*batch_size:(batch+1) *batch_size]
                batch_y = train_labels[batch*batch_size:(batch+1)*batch_size]
                #进行训练 ' '
                sess.run(train_step,feed_dict = {x:batch_x , y:batch_y})
            #每_轮计算一次准确度
            accuracy_n = sess.run(accuracy,feed_dict= { x:validation_images,y: validation_labels})
            strs = ("第"+ str(epoch + 1 ) +"轮，准确率为：" +str(accuracy_n)) + "\n" + strs
        if os.path.exists("/plpy/model_file/%s"%model_name) == False:
            os.mkdir("/plpy/model_file/%s"%model_name)
        saver.save(sess, "/plpy/model_file/%s/tf_model"%model_name)
        return strs;

def predict(test_data,model_name):
    #model_name = 'model1'
    with tf.Session() as sess:
      init = tf.global_variables_initializer()
      sess.run(init)
      #加载模型
      saver = tf.train.import_meta_graph('/plpy/model_file/%s/tf_model.meta'%model_name)
      saver.restore(sess,"/plpy/model_file/%s/tf_model"%model_name )
      graph = tf.get_default_graph()
      prediction = graph.get_tensor_by_name("czcprediction:0")
      x = graph.get_tensor_by_name("input_image:0")
      #进行预测
      pr = sess.run(prediction, feed_dict={x: test_data})
      return pr

#查询数据
# train_data = pd.read_csv('./data/train.csv')
# images = train_data.iloc[:, 1:].values
# # 矩阵拉平
# t_labels = train_data.iloc[:,0:1].values;
# labels_flat = t_labels.ravel()
#
# # 2 对输入数据进行处理
# images = images.astype(np.float)
# images = np.multiply(images, 1.0 / 255.0)
# print("输入数据的数量：（%g,%g）" % images.shape)
# image_size = images.shape[1]
# print('输入的数据维度=>{0}'.format(image_size))
# 调用训练函数
# print(tf_cnn_train(images,labels_flat,'nn_model',50))

test_data =  pd.read_csv('./data/test.csv')
print(predict(test_data,"nn_model"))